package uk.ac.cam.echo.app;

import java.io.IOException;
import java.util.LinkedList;
import uk.ac.cam.echo.messages.UserMessage;
import uk.ac.cam.echo.social.FacebookClient;
import uk.ac.cam.echo.social.StringEventListener;
import android.content.Context;
import android.content.Intent;
import android.hardware.Camera;
import android.hardware.Camera.Parameters;
import android.hardware.Camera.PictureCallback;
import android.hardware.Camera.Size;
import android.os.Bundle;
import android.os.Vibrator;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.Toast;

/**
 * @author Vladimir Kovalev
 */

// TODO: Add repeated documentation.

public class PhotoActivity extends SecondaryActivity
{
	private byte[] currentPictureData = null;
	private Camera camera = null;
	private Scanner rfidScanner;
	private Vibrator vibrator;
	private LinkedList<String> taggedFriendsTags = new LinkedList<String>();
	private LinkedList<String> taggedFriendsFBs = new LinkedList<String>();

	private enum ActivityState {
		Normal, UploadingPicture, PictureTakenScanning, PictureTaken
	};

	private Button homeButton;
	private Button takePhotoButton;
	private Button cancelPreviewButton;
	private Button uploadPhotoButton;
	private Button tagFriendsButton;
	private Button doneTaggingButton;
	private View scannerAnimation;
	private View uploadingAnimation;

	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);

		setContentView(R.layout.photo);
		rfidScanner = new Scanner(self);
		vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);

		homeButton = (Button) findViewById(R.id.photoHomeButton);
		takePhotoButton = (Button) findViewById(R.id.takePhoto);
		cancelPreviewButton = (Button) findViewById(R.id.cancelPreview);
		uploadPhotoButton = (Button) findViewById(R.id.photoUpload);
		tagFriendsButton = (Button) findViewById(R.id.tagPhoto);
		doneTaggingButton = (Button) findViewById(R.id.photoTaggingDone);

		scannerAnimation = findViewById(R.id.scannerAnimation);
		uploadingAnimation = findViewById(R.id.uploadingAnimation);

		final StringEventListener majorErrorListener = new StringEventListener()
		{

			@Override
			public void respondToEvent(String result)
			{
				showOKMessage(result);
				setActivityState(ActivityState.Normal);
				if (camera != null)
					camera.startPreview();
			}
		};

		try
		{
			camera = Camera.open();
		}
		catch (Exception e)
		{
			terminate("PhotoActivity has terminated due to the following camera error:\n" + e.toString());
		}

		Parameters p = camera.getParameters();
		p.setPictureFormat(android.graphics.ImageFormat.JPEG);
		p.setJpegQuality(100);

		for (Size s : p.getSupportedPictureSizes())
		{
			if (s.height > 750)
			{
				p.setPictureSize(s.width, s.height);
			}
		}

		camera.setDisplayOrientation(90);
		camera.setParameters(p);
		final FrameLayout videoPreviewFrame = (FrameLayout) findViewById(R.id.camera_preview);
		final CameraPreview videoPreview = new CameraPreview(this, camera);
		videoPreviewFrame.addView(videoPreview);

		homeButton.setOnClickListener(new OnClickListener()
		{
			@Override
			public void onClick(View v)
			{
				goHome();
			}
		});

		takePhotoButton.setOnClickListener(new OnClickListener()
		{
			@Override
			public void onClick(View v)
			{
				camera.takePicture(null, null, new PictureCallback()
				{
					@Override
					public void onPictureTaken(final byte[] arg0, Camera arg1)
					{
						currentPictureData = arg0;
						setActivityState(ActivityState.PictureTaken);
					}
				});
			}
		});

		cancelPreviewButton.setOnClickListener(new OnClickListener()
		{
			@Override
			public void onClick(View arg0)
			{
				taggedFriendsFBs.clear();
				taggedFriendsTags.clear();

				camera.startPreview();
				setActivityState(ActivityState.Normal);
				rfidScanner.stopSniffing();
				currentPictureData = null;
			}
		});

		uploadPhotoButton.setOnClickListener(new OnClickListener()
		{
			@Override
			public void onClick(View v)
			{
				if (currentPictureData != null)
				{
					setActivityState(ActivityState.UploadingPicture);
					rfidScanner.stopSniffing();

					try
					{
						FacebookClient c = FacebookClient.getInstance();
						c.uploadPictureToGroup(currentPictureData, "", taggedFriendsFBs, new StringEventListener()
						{
							@Override
							public void respondToEvent(final String s)
							{
								showMessage(s, true);
								setActivityState(ActivityState.Normal);

								taggedFriendsFBs.clear();
								taggedFriendsTags.clear();

								// restart preview
								camera.startPreview();
							}
						}, majorErrorListener);
					}
					catch (Throwable e)
					{
						majorErrorListener.respondToEvent("Error uploading picture:\n" + e.toString());
					}
				}
			}
		});

		tagFriendsButton.setOnClickListener(new OnClickListener()
		{
			@Override
			public void onClick(View v)
			{
				setActivityState(ActivityState.PictureTakenScanning);
				rfidScanner.startSniffing();
			}
		});

		doneTaggingButton.setOnClickListener(new OnClickListener()
		{

			@Override
			public void onClick(View arg0)
			{
				setActivityState(ActivityState.PictureTaken);
				rfidScanner.stopSniffing();
			}
		});
	}

	@Override
	public void onNewIntent(final Intent intent)
	{
		super.onNewIntent(intent);

		final String tag = Scanner.decode(intent);
		if (tag != null)
		{
			vibrator.vibrate(60);

			if (taggedFriendsTags.contains(tag))
			{
				Toast.makeText(self, "The friend has already been tagged, taggind failed.", Toast.LENGTH_SHORT).show();
			}
			else
			{
				taggedFriendsTags.add(tag);
				Thread t = new Thread()
				{
					@Override
					public void run()
					{
						UserMessage message = null;
						try
						{
							if (DBInt.getInstance() == null)
							{
								taggedFriendsTags.remove(tag);
								showOKMessage("Problem connecting to the database.");
								setActivityState(ActivityState.PictureTaken);
								return;
							}

							message = (UserMessage) DBInt.getInstance().scanRFID(tag);
							String facebookID = message.getFacebookID();
							final String name = message.getForename() + " " + message.getSurname();

							if (facebookID == null)
							{
								taggedFriendsTags.remove(tag);
								showMessage("Unfortunately this friend has not specified their facebook ID.", false);
								return;
							}

							taggedFriendsFBs.add(facebookID);
							showMessage(name + " has been tagged.", true);

						}
						catch (IOException e)
						{
							taggedFriendsTags.remove(tag);
							showOKMessage("Problem connecting to the database.");
							setActivityState(ActivityState.PictureTaken);
						}
						catch (InterruptedException e)
						{
							taggedFriendsTags.remove(tag);
						}
					}
				};

				t.start();
			}
		}
	}

	@Override
	public void onResume()
	{
		super.onResume();
		rfidScanner.resume();
	}

	@Override
	public void onPause()
	{
		super.onPause();
		rfidScanner.pause();
	}

	@Override
	public void onStop()
	{
		if (camera != null)
			camera.release();

		super.onStop();
	}

	private void setActivityState(ActivityState state)
	{
		switch (state)
		{
		case Normal:
			hideView(cancelPreviewButton);
			hideView(uploadingAnimation);
			hideView(scannerAnimation);
			hideView(doneTaggingButton);

			showView(takePhotoButton);
			showView(tagFriendsButton);

			enableButton(homeButton);
			enableButton(takePhotoButton);

			disableButton(tagFriendsButton);
			disableButton(uploadPhotoButton);
			break;

		case PictureTaken:
			hideView(takePhotoButton);
			hideView(uploadingAnimation);
			hideView(scannerAnimation);
			hideView(doneTaggingButton);

			showView(cancelPreviewButton);
			showView(tagFriendsButton);

			enableButton(homeButton);
			enableButton(takePhotoButton);
			enableButton(tagFriendsButton);
			enableButton(uploadPhotoButton);
			break;

		case PictureTakenScanning:
			hideView(takePhotoButton);
			hideView(uploadingAnimation);
			hideView(tagFriendsButton);

			showView(doneTaggingButton);
			showView(cancelPreviewButton);
			showView(uploadPhotoButton);
			showView(scannerAnimation);

			enableButton(homeButton);
			enableButton(uploadPhotoButton);
			break;

		case UploadingPicture:
			hideView(scannerAnimation);
			hideView(doneTaggingButton);
			hideView(cancelPreviewButton);

			showView(takePhotoButton);
			showView(tagFriendsButton);
			showView(uploadingAnimation);

			disableButton(homeButton);
			disableButton(takePhotoButton);
			disableButton(tagFriendsButton);
			disableButton(uploadPhotoButton);
			break;
		}
	}
}
